package org.rcgwt.client.ui.datechooser;

import java.util.Date;

import org.rcgwt.client.ui.calendar.RichCalendar;
import org.rcgwt.client.ui.calendar.event.InvalidDateEvent;
import org.rcgwt.client.ui.calendar.event.InvalidDateHandler;
import org.rcgwt.client.ui.calendar.i18n.CalendarLiteral;
import org.rcgwt.client.ui.calendar.model.impl.SelectionCardinality;
import org.rcgwt.client.ui.calendar.model.impl.SelectionType;
import org.rcgwt.client.ui.themes.DateChooserTheme;
import org.rcgwt.client.ui.themes.IDateChooserTheme;
import org.rcgwt.client.ui.themes.StandardTheme.RendererLevel;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;

public class DateChooser extends Composite {

	/* Themes */
	private IDateChooserTheme theme;

	/* Controls */
	private HorizontalPanel rootPanel;
	private TextBox dateField;
	private Button dateButton;
	private RichCalendar richCalendar;
	private PopupPanel popup;

	/* Fields */
	private Date previousDate;
	private DateTimeFormat dateFormat;
	private boolean isPopupOpened;

	/**
	 * The Default constructor *
	 */

	public DateChooser() {
		this(CalendarLiteral.getDateLitteral());
	}

	public DateChooser(String datePattern) {
		this(datePattern, new DateChooserTheme());
	}

	public DateChooser(String datePattern, IDateChooserTheme theme) {
		dateFormat = DateTimeFormat.getFormat(datePattern);
		this.theme = theme;
		this.render();
		initWidget(rootPanel);
	}

	private void render() {
		isPopupOpened = false;
		rootPanel = new HorizontalPanel();

		// Date input field
		dateField = new TextBox();
		dateField.addBlurHandler(new BlurHandler() {
			@Override
			public void onBlur(BlurEvent event) {
				// Change date picker value.
				if (dateField.getText().isEmpty() == true) {
					return;
				}
				Date dt = dateFormat.parse(dateField.getText());
				richCalendar.setValue(dt);
			}
		});
		rootPanel.add(dateField);

		// Date chooser button
		dateButton = new Button();
		dateButton.addStyleName(theme.getDateButtonStyle().getClassName());
		rootPanel.add(dateButton);

		dateButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				isPopupOpened = true;
				popup.showRelativeTo(DateChooser.this.dateButton);
				if (dateField.getText().isEmpty() == true) {
					return;
				}
				Date d = dateFormat.parse(dateField.getText());
				if (richCalendar.setValue(d) == false) {
					// Window.alert(messages.invalidDate() + " for " + d);
					if (previousDate != null) {
						dateField.setText(dateFormat.format(previousDate));
						richCalendar.setValue(previousDate);
					} else {
						dateField.setText(dateFormat.format(new Date()));
					}
				} else {
					previousDate = d;
					richCalendar.setValue(d);
				}
				richCalendar.focus();
				richCalendar.getModel().setSelectionType(SelectionType.DATE);
			}
		});

		// Calendar popup
		popup = new PopupPanel(true);
		popup.setStyleName(theme.getPopupPanelStyle().getClassName());

		richCalendar = new RichCalendar(RendererLevel.SIMPLE,
				SelectionCardinality.SINGLE, true, false);
		richCalendar.addStyleName(theme.getRichCalendarStyle().getClassName());

		popup.setWidget(richCalendar);
		richCalendar.addValueChangeHandler(new ValueChangeHandler<Date>() {
			@Override
			public void onValueChange(ValueChangeEvent<Date> event) {
				if (isPopupOpened) {
					isPopupOpened = false;
					popup.hide();
					Date dt = event.getValue();
					dateField.setText(dateFormat.format(dt));
				}
			}
		});

		richCalendar.addInvalidDateHandler(new InvalidDateHandler() {
			@Override
			public void onInvalidDate(InvalidDateEvent event) {
				/*
				 * Window.alert(messages.invalidDate() + " for " +
				 * event.getDate() + " (" + event.getEventType() + ")");
				 */
			}
		});
	}

	public void setReadOnly(boolean ro) {
		if (ro == true) {
			this.dateButton.setEnabled(false);
			this.dateButton.setStyleName(theme.getDisabledDateButtonStyle()
					.getClassName());
			this.dateField.setReadOnly(true);
		} else {
			this.dateButton.setEnabled(true);
			this.dateButton.setStyleName(theme.getDateButtonStyle()
					.getClassName());
			this.dateField.setReadOnly(false);
		}
	}

	public boolean isReadOnly() {
		return this.dateField.isReadOnly();
	}

	public Date getValue() {
		return richCalendar.getValue();
	}

	public void setValue(Date newDate) {
		this.richCalendar.setValue(newDate);
		this.dateField.setValue(dateFormat.format(newDate));
	}

	public TextBox getField() {
		return dateField;
	}

	public RichCalendar getCalendar() {
		return richCalendar;
	}
}